package annuaire.rmi.remotedObject.impl;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.Collection;

import annuaire.beans.Admin;
import annuaire.beans.Promotion;
import annuaire.beans.Student;
import annuaire.dao.IAnnuaireDao;
import annuaire.exceptions.BusinessException;
import annuaire.exceptions.DaoException;
import annuaire.rmi.remotedObject.IRemotedAnnuaire;
import annuaire.rmi.remotedObject.IRemotedUser;
import annuaire.tools.MailSender;

/**
 * Classe d'objet distant RMI, servant à gérer l'authentification, ainsi que les
 * services de lecture seulement
 * 
 * @author Yannick Lorenzati & Stephanie Malakian
 */
public class RemotedAnnuaireImpl extends UnicastRemoteObject implements
		IRemotedAnnuaire {

	/**
	 * Référence vers l'unique instance de cette classe.
	 * */
	static private RemotedAnnuaireImpl _instance = null;

	/**
	 * Référence vers la dao.
	 */
	private IAnnuaireDao dao;

	/**
	 * Crée ou renvoie l'unique instance de cette classe.
	 * 
	 * @return Unique instance de la classe annuaire.
	 * @throws RemoteException
	 */
	static public RemotedAnnuaireImpl instance() throws RemoteException {
		if (null == RemotedAnnuaireImpl._instance) {
			RemotedAnnuaireImpl._instance = new RemotedAnnuaireImpl();
		}
		return RemotedAnnuaireImpl._instance;
	}

	/**
	 * @throws RemoteException
	 */
	protected RemotedAnnuaireImpl() throws RemoteException {
		super();
	}

	private static final long serialVersionUID = -5454537336304697947L;

	/*
	 * (non-Javadoc)
	 * 
	 * @see annuaire.rmi.remotedObject.IRemotedAnnuaire#findAllPromosId()
	 */
	@Override
	public Collection<Integer> findAllPromosId() throws RemoteException,
			BusinessException {

		Collection<Integer> result = null;

		try {
			result = dao.listPromotions();

			if (result == null) {
				result = new ArrayList<Integer>();
			}

		} catch (DaoException e) {
			e.printStackTrace();
			throw new BusinessException(e);
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see annuaire.rmi.remotedObject.IRemotedAnnuaire#findAllStudentsId()
	 */
	@Override
	public Collection<Integer> findAllStudentsId() throws RemoteException,
			BusinessException {

		Collection<Integer> result = null;

		try {
			result = dao.listStudents();

			if (result == null) {
				result = new ArrayList<Integer>();
			}

		} catch (DaoException e) {
			e.printStackTrace();
			throw new BusinessException(e);
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * annuaire.rmi.remotedObject.IRemotedAnnuaire#findAllStudentsIdByPromo(int)
	 */
	@Override
	public Collection<Integer> findAllStudentsIdByPromo(int id)
			throws RemoteException, BusinessException {

		if (id < 0) {
			throw new BusinessException("id negatif");
		}

		Collection<Integer> result = null;

		try {
			result = dao.listStudents(id);

			if (result == null) {
				result = new ArrayList<Integer>();
			}

		} catch (DaoException e) {
			e.printStackTrace();
			throw new BusinessException(e);
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see rmi.remotedObject.IAnnuaire#findPromoById(int)
	 */
	@Override
	public Promotion findPromoById(int id, boolean withStudents)
			throws RemoteException, BusinessException {

		if (id < 0) {
			throw new BusinessException("id negatif");
		}

		Promotion result = null;

		try {
			result = dao.searchPromoById(id, withStudents);
		} catch (DaoException e) {
			throw new BusinessException(e);
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see rmi.remotedObject.IAnnuaire#findStudentById(int)
	 */
	@Override
	public Student findStudentById(int id) throws RemoteException,
			BusinessException {

		if (id < 0) {
			throw new BusinessException("id negatif");
		}

		Student result = null;

		try {
			result = dao.searchStudentById(id);
		} catch (DaoException e) {
			throw new BusinessException(e);
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see rmi.remotedObject.IAnnuaire#getPwdByEmail(java.lang.String)
	 */
	@Override
	public void getPwdByEmail(String login) throws RemoteException,
			BusinessException {

		if (login == null || login.equals("")) {
			return;
		}

		Student s = null;
		s = new Student();
		s.setLogin(login);

		s = searchOneStudent(s);

		if (s == null) {
			throw new BusinessException("login inconnu");
		} else if (s.getMail() == null || s.getMail().equals("")) {
			throw new BusinessException("pas d'email pour cette personne");
		} else {
			String msg = "Votre mot de passe est : " + s.getPwd();

			MailSender.sendSimpleMail("noreply@annu.fr", s.getMail(),
					"oubli mdp", msg);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see annuaire.rmi.remotedObject.IRemotedAnnuaire#login(java.lang.String,
	 * java.lang.String)
	 */
	@Override
	public IRemotedUser login(String login, String pwd) throws RemoteException,
			BusinessException {

		if (login == null || login.equals("")) {
			throw new BusinessException("L'authentification neccesite un login");
		}

		if (pwd == null || pwd.equals("")) {
			throw new BusinessException(
					"L'authentification neccesite un password");
		}

		IRemotedUser remotedUser = null;
		Student s = null;
		Admin a = null;

		/** on regarde si l'user est un etudiant */
		s = new Student();
		s.setLogin(login);
		s.setPwd(pwd);
		s = searchOneStudent(s);
		if (s != null && s.getPwd().equals(pwd)) {
			remotedUser = new StudentImpl();
			((RemotedUserImpl) remotedUser).setDao(dao);
			((RemotedUserImpl) remotedUser).setAssociedBean(s);
			((RemotedUserImpl) remotedUser)
					.setRole(IRemotedAnnuaire.roleStudent);

		} else {
			/** on regarde si c'est un administrateur */
			a = new Admin();
			a.setLogin(login);
			a.setPwd(pwd);
			a = searchOneAdmin(a);
			if (a != null && a.getPwd().equals(pwd)) {
				remotedUser = new AdminImpl();
				((RemotedUserImpl) remotedUser).setDao(dao);
				((RemotedUserImpl) remotedUser).setAssociedBean(a);
				((RemotedUserImpl) remotedUser)
						.setRole(IRemotedAnnuaire.roleAdmin);
			}
		}

		return remotedUser;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * annuaire.rmi.remotedObject.IRemotedAnnuaire#searchPromo(annuaire.beans
	 * .Promotion, boolean, java.lang.Integer)
	 */
	@Override
	public Collection<Promotion> searchPromo(Promotion pattern,
			boolean withStudents, Integer nbResult) throws RemoteException,
			BusinessException {

		if (pattern == null || nbResult < 0) {
			return null;
		}

		Collection<Promotion> result = null;

		try {
			result = dao.searchPromo(pattern, withStudents, nbResult);
		} catch (DaoException e) {
			e.printStackTrace();
			throw new BusinessException(e);
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see rmi.remotedObject.IAnnuaire#searchStudent(beans.Student)
	 */
	@Override
	public Collection<Student> searchStudent(Student pattern, Integer nbResult)
			throws RemoteException, BusinessException {

		if (pattern == null || nbResult < 0) {
			return null;
		}

		Collection<Student> result = null;

		try {
			result = dao.searchStudents(pattern, nbResult);
		} catch (DaoException e) {
			e.printStackTrace();
			throw new BusinessException(e);
		}

		return result;

	}

	/**
	 * setter de la dao
	 * 
	 * @param dao
	 */
	public void setDao(IAnnuaireDao dao) {
		this.dao = dao;
	}

	/**
	 * Initialise proprement L'objet
	 */
	public void init() {
		System.out.println("AnnuaireImpl.init()");
	}

	/**
	 * Clos proprement l'objet
	 */
	public void close() {
		System.out.println("AnnuaireImpl.close()");
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * annuaire.rmi.remotedObject.IRemotedAnnuaire#searchOnePromo(annuaire.beans
	 * .Promotion, boolean)
	 */
	@Override
	public Promotion searchOnePromo(Promotion pattern, boolean withStudents)
			throws RemoteException, BusinessException {

		if (pattern == null) {
			return null;
		}

		Promotion result = null;

		Collection<Promotion> listP = searchPromo(pattern, withStudents, 1);

		if (listP != null && listP.iterator().hasNext()) {
			result = listP.iterator().next();
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * annuaire.rmi.remotedObject.IRemotedAnnuaire#searchOneStudent(annuaire
	 * .beans.Student)
	 */
	@Override
	public Student searchOneStudent(Student pattern) throws RemoteException,
			BusinessException {

		if (pattern == null) {
			return null;
		}

		Student result = null;

		Collection<Student> listS = searchStudent(pattern, 1);

		if (listS != null && listS.iterator().hasNext()) {
			result = listS.iterator().next();
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * annuaire.rmi.remotedObject.IRemotedAnnuaire#searchOneAdmin(annuaire.beans
	 * .Admin)
	 */
	@Override
	public Admin searchOneAdmin(Admin pattern) throws RemoteException,
			BusinessException {

		if (pattern == null) {
			return null;
		}

		Admin result = null;

		Collection<Admin> listS = searchAdmin(pattern, 1);

		if (listS != null && listS.iterator().hasNext()) {
			result = listS.iterator().next();
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * annuaire.rmi.remotedObject.IRemotedAnnuaire#searchAdmin(annuaire.beans
	 * .Admin, java.lang.Integer)
	 */
	@Override
	public Collection<Admin> searchAdmin(Admin pattern, Integer nbResult)
			throws RemoteException, BusinessException {

		Collection<Admin> result = null;

		if (pattern == null || nbResult < 0) {
			return null;
		}

		try {
			result = dao.searchAdmin(pattern, nbResult);
		} catch (DaoException e) {
			e.printStackTrace();
			throw new BusinessException(e);
		}

		return result;

	}
}
